﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using WindowsPhoneMvp.Binder;
using WindowsPhoneMvp.Navigation;
using WindowsPhoneEssentials.Diagnostics;
using WindowsPhoneEssentials.Abstractions;
using WindowsPhoneMvp.Util;

namespace WindowsPhoneMvp.Phone
{
    public sealed class PageViewHost
    {
        internal readonly PresenterBinder PresenterBinder;

        /// <summary>
        /// Initializes a new instance of the <see cref="PageViewHost"/> class.
        /// </summary>
        /// <param name="page">The page instance that this view host will be responsible for.</param>
        /// <param name="frame"></param>
        public PageViewHost(PhoneApplicationPage page, IPhoneApplicationFrame frame, IPhoneApplicationService service)
        {
            if (page == null)
                throw new ArgumentNullException("page");
            var traceContext = new TraceContextAdapter();
            traceContext.Write(this, () => "Creating new PageViewHost instance.");
            var hosts = FindHosts(page).ToArray();
            PresenterBinder = new PresenterBinder(hosts, frame, service);
            page.Unloaded += PageUnloaded;
        }

        internal NavigationServiceContext NavigationContext { get; set; }

        private bool pendingActivation;
        internal bool PendingActivation
        {
            get
            {
                var retval = pendingActivation;
                pendingActivation = false;
                return retval;
            }
            set { pendingActivation = value; }
        }

        internal void PerformBinding()
        {
            PresenterBinder.PerformBinding();
        }

        private static IEnumerable<object> FindHosts(UIElement page)
        {
            yield return page;
        }

        void RegisterView(IView view)
        {
            PresenterBinder.RegisterView(view);
        }

        public static void Register<T>(T control)
            where T : UserControl, IView
        {
            if (control == null)
                throw new ArgumentNullException("control");

            var traceContext = new TraceContextAdapter();

            var viewHost = FindViewHost(control, 
                NavigationServiceContext.RootApplicationContext, 
                NavigationServiceContext.RootApplicationService, 
                traceContext);
            viewHost.RegisterView(control);
        }

        public static PageViewHost BindOnNagivate;

        internal static PageViewHost FindViewHost(UserControl control, 
            IPhoneApplicationFrame frame,
            IPhoneApplicationService service,
            ITraceAppender traceContext)
        {
            traceContext.WriteLine("Finding PageViewHost instance.");

            var parent = BindOnNagivate;
            if (parent != null) return parent;

            if (control is PhoneApplicationPage)
            {
                BindOnNagivate = new PageViewHost(control as PhoneApplicationPage, frame, service);
                return BindOnNagivate;
            }
            throw new ArgumentException("Expected a PhoneApplicationPage before controls can be loaded", "control");
        }

        void PageUnloaded(object sender, RoutedEventArgs e)
        {
            PresenterBinder.DeactivatePresenters();
        }
    }
}
